libbpf-rs
libbpf-rs
is a safe, idiomatic, and opinionated wrapper around
libbpf.
libbpf-rs, together with libbpf-cargo
(libbpf cargo plugin) allow you
to write Compile-Once-Run-Everywhere (CO-RE) eBPF programs. Note this document
uses "eBPF" and "BPF" interchangeably.
More information about CO-RE is available here.
High level workflow
- Create new rust project (via
cargo new
or similar) at path$PROJ_PATH
- Create directory
$PROJ_PATH/src/bpf
- Write CO-RE bpf code in
$PROJ_PATH/src/bpf/${MYFILE}.bpf.c
, where$MYFILE
may be any valid filename. Note the.bpf.c
extension is required. - Create a build script
that builds and generates a skeleton module using
libbpf_cargo::SkeletonBuilder
- Write your userspace code by importing and using the generated module. Import the
module by using the path
attribute.
Your userspace code goes in
$PROJ_PATH/src/
as it would in a normal rust project. - Continue regular rust workflow (ie
cargo build
,cargo run
, etc)
Alternate workflow
While using the skeleton is recommended, it is also possible to directly use libbpf-rs.
- Follow steps 1-3 of "High level workflow"
- Generate a BPF object file. Options include manually invoking
clang
, creating a build script to invokeclang
, or usinglibbpf-cargo
cargo plugins. - Write your userspace code in
$PROJ_PATH/src/
as you would a normal rust project and point libbpf-rs at your BPF object file - Continue regular rust workflow (ie
cargo build
,cargo run
, etc)
Design
libbpf-rs models various "phases":
from_*() load()
| |
v v
ObjectBuilder -> OpenObject -> Object
^ ^
| |
<pre-load modifications> |
|
<post-load interactions>
The entry point into libbpf-rs is [ObjectBuilder
]. ObjectBuilder
helps open the BPF object
file. After the object file is opened, you are returned an [OpenObject
] where you can
perform all your pre-load operations. Pre-load means before any BPF maps are created or BPF
programs are loaded and verified by the kernel. Finally, after the BPF object is loaded, you
are returned an [Object
] instance where you can read/write to BPF maps, attach BPF programs
to hooks, etc.
You must keep the [Object
] alive the entire duration you interact with anything inside the
BPF object it represents. This is further documented in [Object
] documentation.
Example
This is probably the best way to understand how libbpf-rs and libbpf-cargo work together.